using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;

namespace UpdateAuto
{
	public partial class TaskPanel : Panel
	{
		public List<TaskPanelItem> List = new List<TaskPanelItem>();
		private Point NextPanelPoint = new Point(0, 0);
		private int TaskPanelItemHeight = 70;
		public bool RemoveItemsWhenFinished = false;
		public bool RemoveItemsOnError = false;
		public bool AutoSizeForm = true;

		public TaskPanel()
		{
			InitializeComponent();
			this.TaskPanelItemHeight = new TaskPanelItem().Height;
		}

		/// <summary>
		/// Add a task to the panel.  The icon for 'processing' is not set until StartOperation is called
		/// </summary>
		/// <param name="op"></param>
		public void AddOperation(TaskPanelOperation op)
		{
			lock(this)
			{
				System.Diagnostics.Debug.WriteLine(String.Format("Adding panel with guid {0} for task {1}", op.Guid, op.Text));
				// add the item to the end of the form
				TaskPanelItem p = new TaskPanelItem(op);
				op.Status = TaskStatus.Waiting;
				p.Anchor = AnchorStyles.Top | AnchorStyles.Left | AnchorStyles.Right;
				p.Location = NextPanelPoint;
				p.Width = this.Width - 30;
				this.Controls.Add(p);
				List.Add(p);

				if(AutoSizeForm && this.List.Count > 1)	// && this.Parent is Form && (this.Parent as Form).WindowState != FormWindowState.Minimized)
				{
					// increase the size of the form
					this.Parent.Height = Math.Min(550, 80 + TaskPanelItemHeight * this.List.Count);//this.Parent.Height + TaskPanelItemHeight);
				}
				NextPanelPoint.Y += TaskPanelItemHeight;
			}
		}

		delegate void StartOperationDelegate(string Guid);
		public void StartOperation(string Guid)
		{
			if(this.InvokeRequired)
			{
				Invoke(new StartOperationDelegate(this.StartOperation), new object[] { Guid});
				return;
			} 
			lock(this)
			{
				TaskPanelItem tp = (this.Controls["pnl" + Guid.Replace("-", "")] as TaskPanelItem);
				if(tp == null)
				{
					System.Diagnostics.Debug.WriteLine("Error task panel item not found for guid " + Guid);
					return;
				}
				tp.op.Status = TaskStatus.Running;
				tp.pictureBox1.Image = this.imageList1.Images[0];
				tp.progressBar1.Visible = true;
			}
		}

		delegate void EndOperationDelegate(string Guid, Exception ex);
		public void EndOperation(string Guid, Exception ex)
		{
			if(this.InvokeRequired)
			{
				Invoke(new EndOperationDelegate(this.EndOperation), new object[] { Guid, ex });
				return;
			}
			lock(this)
			{
				System.Diagnostics.Debug.WriteLine(String.Format("Removing panel with guid {0}", Guid));

				TaskPanelItem tp = (this.Controls["pnl" + Guid.Replace("-", "")] as TaskPanelItem);
				if(tp == null)
				{
					System.Diagnostics.Debug.WriteLine("Error task panel item not found for guid " + Guid);
					return;
				}
				tp.progressBar1.Visible = false;

				if(ex == null)	// set the icon to complete
				{
					tp.op.Status = TaskStatus.Success;
					tp.pictureBox1.Image = this.imageList1.Images[1];
					tp.lblStatus.Text = "Complete";
				}
				else
				{
					tp.op.Status = TaskStatus.Failed;
					tp.pictureBox1.Image = this.imageList1.Images[2];
					tp.lblStatus.Text = ex.Message;
				}

				if(!this.RemoveItemsWhenFinished)	// leave the task as it is
					return;
				else if(!this.RemoveItemsOnError && ex != null)	// there is an error, and the task should not be removed.
					return;

				// remove from the array list
				TaskPanelItem itemToRemove = null;
				int i = 0;	// store the position of the removed item, so we can move all items below, up one position
				foreach(TaskPanelItem item in List)
				{
					i++;
					if(item.op.Guid == Guid)
					{
						itemToRemove = item;
						break;
					}
				}
				if(itemToRemove != null)
				{
					List.Remove(itemToRemove);
					i--;
				}

				// remove the panel from the user interface
				Control ToRemove = null;
				foreach(Control c in this.Controls)
				{
					if(c.Name == "pnl" + Guid.Replace("-", ""))
					{
						ToRemove = c;
						break;
					}
				}
				if(ToRemove != null)
					this.Controls.Remove(ToRemove);

				// decrement the next panel point
				NextPanelPoint.Y -= TaskPanelItemHeight;

				// move items below up one position.  "i" holds the index of the panel to start moving up
				for(int j = i; j < List.Count; j++)
				{
					string pnlName = "pnl" + List[j].op.Guid.Replace("-", "");
					if(this.Controls[pnlName] == null)
						continue;
					else
						this.Controls[pnlName].Top -= TaskPanelItemHeight;
				}
			}
		}

		delegate void ProgressChangedDelegate(string Guid, int ProgressPercentage, string Message);
		public void ProgressChanged(string Guid, int ProgressPercentage, string Message)
		{
			if(this.InvokeRequired)
			{
				Invoke(new ProgressChangedDelegate(this.ProgressChanged), new object[] { Guid, ProgressPercentage, Message });
				return;
			}
			string ControlName = "pnl" + Guid.Replace("-", "");
			if(this.Controls[ControlName] == null)
				return;
			TaskPanelItem item = this.Controls[ControlName] as TaskPanelItem;
			item.lblStatus.Text = Message;
			if(ProgressPercentage > 0 && ProgressPercentage < item.progressBar1.Maximum)
			{
				item.progressBar1.Value = ProgressPercentage;
				item.progressBar1.Visible = (Message.ToLower().IndexOf("waiting") < 0);
			}
		}
	}
}
